package environment;

import java.util.ArrayList;
import java.util.List;

public class PhysicalMachine {

	private Integer id;
	private Integer loadCPUs;
	private Integer maxCPUs;
	
	private boolean isRunning;
	private boolean isMaybeTerminated;
	
	private List<VirtualMachine> virtualMachines = 
		new ArrayList<VirtualMachine>();
	
	public PhysicalMachine(Integer id, Integer maxCPUs) {
		this.id = id;
		this.loadCPUs = 0;
		this.maxCPUs = maxCPUs;
		this.isRunning = false;
		this.isMaybeTerminated = false;
	}

	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	
	public Integer getLoadCPUs() {
		synchronized(loadCPUs) {
			return loadCPUs;
		}
	}
	public void addLoadCPUs(Integer loadCPUs) {
		synchronized(this.loadCPUs) {
			this.loadCPUs += loadCPUs;
		}
	}
	public void removeLoadCPUs(Integer loadCPUs) {
		synchronized(this.loadCPUs) {
			this.loadCPUs -= loadCPUs;
		}
	}
	
	public Integer getMaxCPUs() {
		return maxCPUs;
	}

	public List<VirtualMachine> getVirtualMachines() {
		return virtualMachines;
	}
	public boolean isRunning() {
		return isRunning;
	}
	public void setRunning(boolean isRunning) {
		this.isRunning = isRunning;
	}
	
	public boolean isMaybeTerminated() {
		return isMaybeTerminated;
	}

	public void setMaybeTerminated(boolean isMaybeTerminated) {
		this.isMaybeTerminated = isMaybeTerminated;
	}

	public Integer getFreeCPUs()
	{
		return getMaxCPUs() - getLoadCPUs();
	}
	
	public void start()
	{
		setRunning(true);
	}
	
	public void stop()
	{
		setRunning(false);
		// remove vms
		synchronized(virtualMachines)
		{
			for(int i=virtualMachines.size()-1; i >= 0; i--)
				removeVirtualMachine(virtualMachines.get(0));
		}
	}

	public void addVirtualMachine(VirtualMachine vm)
	{
		if(vm != null)
		{
			synchronized(virtualMachines) {
				virtualMachines.add(vm);
			}
			if(vm.getPhysicalMachine() != this)
				vm.setPhysicalMachine(this);
			
			/* adapt load */
			addLoadCPUs(vm.getMaxCPUs());
		}
	}
	
	public void removeVirtualMachine(VirtualMachine vm)
	{
		if(vm != null)
		{
			synchronized(virtualMachines) {
				virtualMachines.remove(vm);
			}
			vm.setPhysicalMachine(null);
			
			/* adapt load */
			//removeLoadCPUs(vm.getMaxCPUs());
		}
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		PhysicalMachine other = (PhysicalMachine) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "PhysicalMachine [id=" + id + ", loadCPUs=" + loadCPUs
				+ ", maxCPUs=" + maxCPUs
				+ ", isRunning=" + isRunning + "]";
	}
}
